package java核心及工具类.Format类;

/*Format 是一个用于格式化语言环境敏感的信息（如日期、消息和数字）的抽象基类。 Format 定义了编程接口，用于将语言环境敏感的对象格式化为String（使用 format 方法）
和将 String 重新解析为对象（使用 parseObject 方法）。
通常，一个 format 的 parseObject方法必须能解析任何由其 format 方法格式化的字符串。不过，也可能存在不能解析的异常情况。例如，format 方法可能创建中间无分隔
符的两个相邻整数，在这种情况下，parseObject 无法判断哪个数字属于哪个数。

Java 平台为格式化日期、消息和数字分别提供了三个特殊的Format 的子类：DateFormat、MessageFormat 和 NumberFormat。
具体的子类必须实现三个方法：

format(Object obj, StringBuffertoAppendTo, FieldPosition pos)
formatToCharacterIterator(Object obj)
parseObject(String source,ParsePosition pos)

Format  ---> DateFormat   ---> SimpleDateFormat   日期类格式化
        ---> MessageFormat---> 
        ---> NumberFormat ---> DecimalFormat      数字类格式化
                          ---> ChoiceFormat


这些常规方法允许对对象进行多态解析和格式化，还可以被使用（如被 MessageFormat 使用）。子类通常也为特定的输入类型提供了另外的 format 方法，也为特定的结果类型提
供了parse 方法。当在输入文本的开始没有任何所需格式的文本时，则任何不带 ParsePosition 参数的 parse 方法都应该抛出 ParseException。

大多数子类还将实现以下工厂方法：

getInstance 获取一个适合于当前语言环境的有用的格式对象

getInstance(Locale)获取一个适合于指定语言环境的有用的格式对象。

此外，某些子类还可能为了更特殊的控制实现其它 getXxxxInstance 方法。例如，NumberFormat 类提供了 getPercentInstance 和 getCurrencyInstance 方法
来获取特殊的数字格式器。

Format 的子类如果允许程序员能为不同语言环境（比如用 getInstance(Locale) ）创建对象，必须实现以下类方法：

 public staticLocale[] getAvailableLocales()

 最后子类定义一个常量集合来标识格式输出中的不同字段。这些常量用于创建一个 FieldPosition 对象，该对象标识字段中所包含的信息及其在格式化结果中的位置。这些常量应当
 命名为item _FIELD，其中item 标识了该字段。有关这些常量的例子，请参阅 ERA_FIELD 及其在 DateFormat 中的同类。
创建Format类的实例
因为Format是抽象类，所以我们无法通过Format 的构造方法（非公有的）来实例化Format类的对象。如下面的写法是错误的：
Format format=new Format();
那么我们如何实例化Format类的实例呢?
我们可以利用Java面向对象语言的多态性来解决这个问题：

通过父类型的引用可以指向子类型的对象，说白了就是用子类去实例化父类的对象。
*/
/*
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Format类 {
	public static void main(String[] args) {

        NumberFormat myFormat = NumberFormat.getNumberInstance();
        FieldPosition fp = new FieldPosition(NumberFormat.INTEGER_FIELD);
        myFormat.setMaximumIntegerDigits(3);//整数部分最大位数
        myFormat.setMaximumFractionDigits(2);//小数部分最大位数
        myFormat.setMinimumFractionDigits(2);//小数部分最小位数

        System.out.println("Degrees  Radians  Grads");
        for (double degrees = 0.0; degrees < 360.0; degrees++) {
            String radianString = myFormat.format(Math.PI * degrees / 180.0, new StringBuffer(), fp).toString();
            radianString = getSpaces(3 - fp.getEndIndex()) + radianString;
            String gradString = myFormat.format(400 * degrees / 360, new StringBuffer(), fp).toString();
            gradString = getSpaces(3 - fp.getEndIndex()) + gradString;
            String degreeString = myFormat.format(degrees, new StringBuffer(), fp).toString();
            degreeString = getSpaces(3 - fp.getEndIndex()) + degreeString;
            System.out.println(degreeString + "  " + radianString + "  " + gradString);
        }
       Date d=new Date();
       System.out.println(DateToString(d));
       
       
	}
    public static String getSpaces(int n) {

         StringBuffer sb = new StringBuffer(n);
         for (int i = 0; i < n; i++)
             sb.append(' ');
         return sb.toString();
    }
    public static String DateToString(Date inDate) {
        String toTemplate = "dd-MMM-yy";
        return DateToString(inDate, toTemplate);
    }

    public static String DateToString(Date inDate, String toTemplate) {
        FieldPosition f = new FieldPosition(2);
        SimpleDateFormat sd = new SimpleDateFormat(toTemplate);
        StringBuffer sb = new StringBuffer();
        StringBuffer sb2 = new StringBuffer();
        sb = sd.format(inDate, sb2, f);
        return sb.toString();
    }
}
*/
//【SimpleDateFormat】
//简介
//扩展了DateFormat
//
//SimpleDateFormat是一个具体的类，用于以语言环境敏感的方式格式化和解析日期。它允许格式化（日期 -> 文本）、解析（文本 -> 日期）和规范化。
//
//SimpleDateFormat允许您首先为日期时间格式选择任何用户定义的模式。不过，建议您创建一个日期-时间格式有两种
//getTimeInstance，getDateInstance或 getDateTimeInstance在DateFormat。这些类方法中的每一个都可以返回一个使用默认格式模式初始化的日期/时间格式化程
//序。您可以applyPattern根据需要使用方法修改格式模式。有关使用这些方法的更多信息，请参阅 DateFormat。
//
//SimpleDateFormat 允许以为日期-时间格式化选择任何用户指定的方式启动。 但是，希望用 DateFormat 中的 getTimeInstance、 getDateInstance 
//或 getDateTimeInstance 创建一个日期-时间格式化程序。 每个类方法返回一个以缺省格式化方式初始化的日期／时间格式化程序。 可以根据需要用 applyPattern 方法修
//改格式化方式。
//
//例子
import java.text.*;
import java.util.Date;

/*
  SimpleDateFormat函数语法：
 
  G 年代标志符
  y 年
  M 月
  d 日
  h 时 在上午或下午 (1~12)
  H 时 在一天中 (0~23)
  m 分
  s 秒
  S 毫秒
  E 星期
  D 一年中的第几天
  F 一月中第几个星期几
  w 一年中第几个星期
  W 一月中第几个星期
  a 上午 / 下午 标记符
  k 时 在一天中 (1~24)
  K 时 在上午或下午 (0~11)
  z 时区
*/
/*
//public class FormatDateTime {
public class Format类 {
    public static void main(String[] args) {
        SimpleDateFormat myFmt=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        SimpleDateFormat myFmt1=new SimpleDateFormat("yy/MM/dd HH:mm");
        SimpleDateFormat myFmt2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//等价于now.toLocaleString()
        SimpleDateFormat myFmt3=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 E ");
        SimpleDateFormat myFmt4=new SimpleDateFormat("一年中的第 D 天 一年中第w个星期 一月中第W个星期 在一天中k时 z时区");
        
//        public abstract class DateFormat extends Format {
//        	//.....
//        	public abstract StringBuffer format(Date date, StringBuffer toAppendTo,FieldPosition fieldPosition);
//        	
//        	public final String format(Date date){
//        		//.....
//                return format(date, new StringBuffer(),DontCareFieldPosition.INSTANCE).toString();
//            }
//        }
//        public class SimpleDateFormat extends DateFormat
        
        
        Date now=new Date();
        System.out.println(myFmt.format(now)); //2022年07月06日 21时02分19秒
        System.out.println(myFmt1.format(now));//22/07/06 21:02
        System.out.println(myFmt2.format(now));//2022-07-06 21:02:19
        System.out.println(myFmt3.format(now));//2022年07月06日 21时02分19秒 周三
        System.out.println(myFmt4.format(now));//一年中的第 187 天 一年中第28个星期 一月中第2个星期 在一天中21时 CST时区
        System.out.println(now.toGMTString());//6 Jul 2022 13:02:19 GMT
        System.out.println(now.toLocaleString());//2022年7月6日 下午9:02:19
        System.out.println(now.toString());//Wed Jul 06 21:02:19 CST 2022
    } 
}
*/
//下面是个JavaBean:

//public class FormatDateTime {
public class Format类1  {
    public static String toLongDateString(Date dt){
        SimpleDateFormat myFmt=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 E ");       
        return myFmt.format(dt);
    }
   
    public static String toShortDateString(Date dt){
        SimpleDateFormat myFmt=new SimpleDateFormat("yy年MM月dd日 HH时mm分");       
        return myFmt.format(dt);
    }   
   
    public static String toLongTimeString(Date dt){
        SimpleDateFormat myFmt=new SimpleDateFormat("HH mm ss SSSS");       
        return myFmt.format(dt);
    }
    public static String toShortTimeString(Date dt){
        SimpleDateFormat myFmt=new SimpleDateFormat("yy/MM/dd HH:mm");       
        return myFmt.format(dt);
    }
   
    public static void main(String[] args) {
        Date now=new Date();

        System.out.println(Format类1.toLongDateString(now));//2022年07月06日 21时32分21秒 周三
        System.out.println(Format类1.toShortDateString(now));//22年07月06日 21时32分
        System.out.println(Format类1.toLongTimeString(now));//21 32 21 0512
        System.out.println(Format类1.toShortTimeString(now));//22/07/06 21:32
        
        //以下是一个显示格式化和解析的简单例子：
        double[] limits = {1,2,3,4,5,6,7};
        String[] dayOfWeekNames = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
        ChoiceFormat form = new ChoiceFormat(limits, dayOfWeekNames);
        ParsePosition status = new ParsePosition(9);
        System.out.println(form.format(-1));
        for (double i = 0.0; i <= 8.0; ++i) {
            status.setIndex(0);
            System.out.println(i + " -> " + form.format(i) + " -> "+ form.parse(form.format(i),status)+" "+status.getIndex()+" "+status);
         }
        
        String s = "Hello";
        System.out.println(s);
        String s1=s;
        s = s.toUpperCase();
        System.out.println(s+" "+s1);
        
    }   
   
}

/*【ChoiceFormat】
public class ChoiceFormat extends NumberFormat {
	//...
	ChoiceFormat(String newPattern)  {
        applyPattern(newPattern);
    }
    public ChoiceFormat(double[] limits, String[] formats) {
        setChoices(limits, formats);
    }
    //...
}
public class ParsePosition {
    int index = 0;
    int errorIndex = -1;
	//...
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }
    public ParsePosition(int index) {
        this.index = index;
    }
    //...
}
*/
//简介
//ChoiceFormat 允许将格式应用到某个范围的数。它通常用于在 MessageFormat 中处理复数。使用按升序排列的 double 列表指定 choice，列表中每一项都指
//定一个到下一项的半开区间：
//
//当且仅当 limit[j] <= X < limit[j+1] 时，X 匹配 j
//
//如果不匹配，则根据数 (X) 的是太小还是太大，选择使用第一个或最后一个索引。如果 limit 数组不按升序排列，则格式化的结果将不正确。ChoiceFormat 还接
//受 $ \infty $（等同于无穷大 (INF)）。
//
//以下是一个显示格式化和解析的简单例子：
/*
double[] limits = {1,2,3,4,5,6,7};
String[] dayOfWeekNames = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
ChoiceFormat form = new ChoiceFormat(limits, dayOfWeekNames);
ParsePosition status = new ParsePosition(0);
for (double i = 0.0; i <= 8.0; ++i) {
    status.setIndex(0);
    System.out.println(i + " -> " + form.format(i) + " -> "+ form.parse(form.format(i),status));
 }
以下是一个较复杂的带模式格式的例子：

double[] filelimits = {0,1,2};
String[] filepart = {"are no files","is one file","are {2} files"};
ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
Format[] testFormats = {fileform, null, NumberFormat.getInstance()};
MessageFormat pattform = new MessageFormat("There {0} on {1}");
pattform.setFormats(testFormats);
Object[] testArgs = {null, "ADisk", null};
for (int i = 0; i < 4; ++i) {
    testArgs[0] = new Integer(i);
    testArgs[2] = testArgs[0];
    System.out.println(pattform.format(testArgs));
}
为 ChoiceFormat 对象指定一个模式是相当直接的。例如：

ChoiceFormat fmt = new ChoiceFormat(
    "-1#is negative| 0#is zero or fraction | 1#is one |1.0<is 1+ |2#is two |2<is more than 2.");
System.out.println("Formatter Pattern : " + fmt.toPattern());

System.out.println("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
System.out.println("Format with -1.0 : " + fmt.format(-1.0));
System.out.println("Format with 0 : " + fmt.format(0));
System.out.println("Format with 0.9 : " + fmt.format(0.9));
System.out.println("Format with 1.0 : " + fmt.format(1));
System.out.println("Format with 1.5 : " + fmt.format(1.5));
System.out.println("Format with 2 : " + fmt.format(2));
System.out.println("Format with 2.1 : " + fmt.format(2.1));
System.out.println("Format with NaN : " + fmt.format(Double.NaN));
System.out.println("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
*/

